﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using Castle.Core.Internal;
using Windows.WorkFlow.Domain;
using Windows.Infrastructure.Share.Extensions;
using Windows.WorkFlow.Domain.Enums;

namespace Windows.WorkFlow.Service
{
    public class FlowRuntime
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public FlowRuntime(FlowInstance instance)
        {
            FlowInstanceId = instance.Id;
            FlowName = instance.Flow!.Name;
            dynamic editorJson = instance.Flow!.EditorJson.ToEntity<dynamic>()!;//获取工作流模板内容的json对象;

            
            InitNodes(editorJson);
            CurrentNodeId = (instance.CurrentNodeId == "" ? StartNodeId : instance.CurrentNodeId);
            InitEdges(editorJson);

            //CurrentNodeType = GetNodeType(currentNodeId);
            //FrmData = instance.FrmData;
            //title = schemeContentJson.title;
            //initNum = schemeContentJson.initNum?? 0;
            //PrevId = instance.PreviousId;

            NextNodeId = GetNextNodeId();//下一个节点
            //会签开始节点和流程结束节点没有下一步
            //if (currentNodeType == 0 || currentNodeType == 4)
            //{
            //    NextNodeId = "-1";
            //    NextNodeType = -1;
            //}
            //else
            //{
            //    NextNodeId = GetNextNodeId();//下一个节点
            //    nextNodeType = GetNodeType(nextNodeId);
            //}
        }

        #region 私有方法

        /// <summary>
        /// 获取工作流节点的字典列表:key节点id
        /// </summary>
        /// <param name="editorJson"></param>
        /// <returns></returns>
        private void InitNodes(dynamic editorJson)
        {
            Nodes = new Dictionary<string, FlowNode>();
            foreach (JObject item in editorJson.nodes)
            {
                var node = item.ToObject<FlowNode>()!;
                if (!Nodes.ContainsKey(node.Id))
                {
                    Nodes.Add(node.Id, node);
                }
                if (node.Type == FlowNodeTypeEnum.StartEvent.ToString())
                {
                    this.StartNodeId = node.Id;
                }
            }
        }

        private void InitEdges(dynamic editorJson)
        {
            Edges = new List<FlowEdge>();
            FromNodeEdges = new Dictionary<string, List<FlowEdge>>();
            ToNodeEdges = new Dictionary<string, List<FlowEdge>>();
            foreach (JObject item in editorJson.edges)
            {
                var edge = item.ToObject<FlowEdge>()!;
                Edges.Add(edge);

                if (CurrentNodeId == edge.TargetNodeId)
                {
                    if (!FromNodeEdges.ContainsKey(edge.TargetNodeId))
                    {
                        FromNodeEdges.Add(edge.TargetNodeId, new List<FlowEdge>() { edge });
                    }
                    else
                    {
                        FromNodeEdges[edge.TargetNodeId].Add(edge);
                    }  
                }
                if (CurrentNodeId == edge.SourceNodeId)
                {
                    if (!ToNodeEdges.ContainsKey(edge.SourceNodeId))
                    {
                        ToNodeEdges.Add(edge.SourceNodeId, new List<FlowEdge>() { edge });
                    }
                    else
                    {
                        ToNodeEdges[edge.SourceNodeId].Add(edge);
                    }
                }
            }
        }

        /// <summary>
        /// 获取下一个节点
        /// </summary>
        private string GetNextNodeId(string? nodeId = null)
        {
            var edges = nodeId == null ? ToNodeEdges[CurrentNodeId] : ToNodeEdges[nodeId];
            if (edges.Count == 0)
            {
                throw new Exception("无法寻找到下一个节点");
            }
            return edges[0].TargetNodeId;
            //if (FrmData == "") return lines[0].SourceNodeId;

            //FrmData = FrmData.ToLower();//统一转小写
            //var frmDataJson = FrmData.ToJObject();//获取数据内容

            //foreach (var l in lines)
            //{
            //    if (!(l.Compares.IsNullOrEmpty()) &&l.Compare(frmDataJson))
            //    {
            //        return l.to;
            //    }
            //}

            //return lines[0].to;
        }

        #endregion 私有方法

        #region 共有方法

        //获取下一个节点
        public FlowNode GetNextNode(string? nodeId = null)
        {
            return Nodes[GetNextNodeId(nodeId)];
        }

        /// <summary>
        /// 获取实例接下来运行的状态
        /// </summary>
        /// <returns>-1无法运行,0会签开始,1会签结束,2一般节点,4流程运行结束</returns>
        //public int GetNextNodeType()
        //{
        //    if (NextNodeId != "-1")
        //    {
        //        return GetNodeType(NextNodeId);
        //    }
        //    return -1;
        //}

        /// <summary>
        /// 获取节点类型 0会签开始,1会签结束,2一般节点,开始节点,4流程运行结束
        /// </summary>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        //public int GetNodeType(string nodeId)
        //{
        //    switch (Nodes[nodeId].type)
        //    {
        //        //会签开始节点
        //        case FlowNode.FORK:
        //            return 0;
        //        //会签结束节点
        //        case FlowNode.JOIN:
        //            return 1;
        //        //结束节点
        //        case FlowNode.END:
        //            return 4;
        //        //开始节点
        //        case FlowNode.START:
        //            return 3;

        //        default:
        //            return 2;
        //    }
        //}

        /// <summary>
        /// 节点会签审核
        /// </summary>
        /// <param name="nodeId">会签时，currentNodeId是会签开始节点。这个表示当前正在处理的节点</param>
        /// <param name="tag"></param>
        /// <returns>-1不通过,1等待,其它通过</returns>
        //public string NodeConfluence(string nodeId, Tag tag)
        //{
        //    var forkNode = Nodes[CurrentNodeId];  //会签开始节点
        //    FlowNode nextNode = GetNextNode(nodeId); //获取当前处理的下一个节点

        //    int forkNumber = FromNodeLines[currentNodeId].Count;   //直接与会签节点连接的点，即会签分支数目
        //    string res =string.Empty;  //记录会签的结果,默认正在会签
        //    if (forkNode.setInfo.NodeConfluenceType == "one") //有一个步骤通过即可
        //    {
        //        if (tag.Taged == (int) TagState.Ok)
        //        {
        //            if (nextNode.type == FlowNode.JOIN)  //下一个节点是会签结束，则该线路结束
        //            {
        //                res = GetNextNodeId(nextNode.id);
        //            }
        //        }
        //        else if(tag.Taged ==(int) TagState.No)
        //        {
        //            if (forkNode.setInfo.ConfluenceNo == null)
        //            {
        //                forkNode.setInfo.ConfluenceNo = 1;
        //            }
        //            else if (forkNode.setInfo.ConfluenceNo == (forkNumber - 1))
        //            {
        //                res = TagState.No.ToString("D");
        //            }
        //            else
        //            {
        //                bool isFirst = true;  //是不是从会签开始到现在第一个
        //                var preNode = GetPreNode(nodeId);
        //                while (preNode.id != forkNode.id) //反向一直到会签开始节点
        //                {
        //                    if (preNode.setInfo != null && preNode.setInfo.Taged == (int) TagState.No)
        //                    {
        //                        isFirst = false;
        //                        break;
        //                    }
        //                }

        //                if (isFirst)
        //                {
        //                    forkNode.setInfo.ConfluenceNo++;
        //                }
        //            }
        //        }
        //    }
        //    else //默认所有步骤通过
        //    {
        //        if (tag.Taged == (int) TagState.No)  //只要有一个不同意，那么流程就结束
        //        {
        //            res = TagState.No.ToString("D");
        //        }
        //        else if(tag.Taged == (int)TagState.Ok)
        //        {
        //            if (nextNode.type == FlowNode.JOIN)  //这种模式下只有坚持到【会签结束】节点之前才有意义，是否需要判定这条线所有的节点都通过，不然直接执行这个节点？？
        //            {
        //                if (forkNode.setInfo.ConfluenceOk == null)
        //                {
        //                    forkNode.setInfo.ConfluenceOk = 1;
        //                }
        //                else if (forkNode.setInfo.ConfluenceOk == (forkNumber - 1))  //会签成功
        //                {
        //                    res = GetNextNodeId(nextNode.id);
        //                }
        //                else
        //                {
        //                    forkNode.setInfo.ConfluenceOk++;
        //                }
        //            }
        //        }
        //    }

        //    if (res == TagState.No.ToString("D"))
        //    {
        //        tag.Taged = (int) TagState.No;
        //        MakeTagNode(nextNode.id, tag);
        //    }
        //    else if (!string.IsNullOrEmpty(res)) //会签结束，标记合流节点
        //    {
        //        tag.Taged = (int) TagState.Ok;
        //        MakeTagNode(nextNode.id, tag);
        //        nextNodeId = res;
        //        nextNodeType = GetNodeType(res);
        //    }
        //    else
        //    {
        //        nextNodeId = nextNode.id;
        //        nextNodeType = GetNodeType(nextNode.id);
        //    }
        //    return res;
        //}
        
        //获取上一个节点
        private FlowNode GetPrevNode(string? nodeId = null)
        {
            var lines = nodeId == null ? FromNodeEdges[CurrentNodeId] : FromNodeEdges[nodeId];
            if (lines.Count == 0)
            {
                throw new Exception("无法找到上一个点");
            }
            return Nodes[lines[0].TargetNodeId];
        }

        /// <summary>
        /// 驳回
        /// </summary>
        /// <param name="rejectType">驳回类型。null:使用节点配置的驳回类型/0:前一步/1:第一步/2：指定节点，使用NodeRejectStep</param>
        /// <returns></returns>
        public string RejectNode(string rejectType)
        {
            dynamic node = Nodes[CurrentNodeId];
            if (node.setInfo != null && string.IsNullOrEmpty(rejectType))
            {
                rejectType = node.setInfo.NodeRejectType;
            }
            
            if (rejectType == "0")
            {
                return PrevId;
            }
            if (rejectType == "1")
            {
                return GetNextNodeId(StartNodeId);
            }
            return PrevId;
        }

        /// <summary>
        /// 撤销流程，清空所有节点
        /// </summary>
        //public void ReCall()
        //{
        //    foreach (var item in Nodes)
        //    {
        //        item.Value.setInfo = null;
        //    }
        //}

        ///<summary>
        /// 标记节点1通过，-1不通过，0驳回
        /// </summary>
        /// <param name="nodeId"></param>
        //public void MakeTagNode(string nodeId, Tag tag)
        //{
        //    foreach (var item in Nodes)
        //    {
        //        if (item.Key == nodeId)
        //        {
        //            if (item.Value.setInfo == null)
        //            {
        //                item.Value.setInfo  = new Setinfo();
        //            }
        //            item.Value.setInfo.Taged = tag.Taged;
        //            item.Value.setInfo.UserId = tag.UserId;
        //            item.Value.setInfo.UserName = tag.UserName;
        //            item.Value.setInfo.Description = tag.Description;
        //            item.Value.setInfo.TagedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
        //            break;
        //        }
        //    }
        //}

        //public object ToSchemeObj()
        //{
        //    return new
        //    {
        //        title = this.title,
        //        initNum = this.initNum,
        //        lines = Lines,
        //        nodes = Nodes.Select(u => u.Value),
        //        areas = new string[0]
        //    };
        //}

        /// <summary>
        /// 通知三方系统，节点执行情况
        /// </summary>
        //public void NotifyThirdParty(HttpClient client, Tag tag)
        //{
        //    if (currentNode.setInfo == null || string.IsNullOrEmpty(currentNode.setInfo.ThirdPartyUrl))
        //    {
        //        return;
        //    }

        //    var postData = new
        //    {
        //        flowInstanceId,
        //        nodeName=currentNode.name,
        //        nodeId = currentNodeId,
        //        userId = tag.UserId,
        //        userName = tag.UserName,
        //        result=tag.Taged, //1：通过;2：不通过；3驳回
        //        description = tag.Description,
        //        execTime = tag.TagedTime,
        //        isFinish = currentNodeType == 4
        //    };

        //    using (HttpContent httpContent = new StringContent(JsonHelper.Instance.Serialize(postData), Encoding.UTF8))
        //    {
        //            httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
        //           client.PostAsync(currentNode.setInfo.ThirdPartyUrl, httpContent);
        //    }
        //}

        #endregion 共有方法

        #region 属性
        /// <summary>
        /// 运行实例的Id
        /// </summary>
        public long FlowInstanceId { get; set; }
        /// <summary>
        /// 工作流的Name
        /// </summary>
        public string FlowName { get; set; }

        /// <summary>
        /// 开始节点的ID
        /// </summary>
        public string StartNodeId { get; set; }

        /// <summary>
        /// 当前节点的ID
        /// </summary>
        public string CurrentNodeId { get; set; }

        /// <summary>
        /// 当前节点类型 0会签开始,1会签结束,2一般节点,开始节点,4流程运行结束
        /// </summary>
        public int CurrentNodeType { get; set; }

        /// <summary>
        /// 当前节点的对象
        /// </summary>
        public FlowNode CurrentNode => Nodes[CurrentNodeId];

        /// <summary>
        /// 下一个节点
        /// </summary>
        public string NextNodeId { get; set; }

        /// <summary>
        /// 下一个节点类型 -1无法运行,0会签开始,1会签结束,2一般节点,4流程运行结束
        /// </summary>
        /// <value>The type of the next node.</value>
        public int NextNodeType { get; set; }

        /// <summary>
        /// 下一个节点对象
        /// </summary>
        public FlowNode? NextNode => NextNodeId != "-1"? Nodes[NextNodeId] : null;

        /// <summary>
        /// 上一个节点
        /// </summary>
        public string PrevId { get; set; }

        /// <summary>
        /// 实例节点集合
        /// </summary>
        public Dictionary<string, FlowNode> Nodes { get; set; }

        /// <summary>
        /// 流程实例中所有的线段
        /// </summary>
        public List<FlowEdge> Edges { get; set; }

        /// <summary>
        /// 从节点发出的线段集合
        /// </summary>
        public Dictionary<string, List<FlowEdge>> FromNodeEdges { get; set; }

        /// <summary>
        /// 到达节点的线段集合
        /// </summary>
        public Dictionary<string, List<FlowEdge>> ToNodeEdges { get; set; }

        /// <summary>
        /// 表单数据
        /// </summary>
        public string FrmData { get; set; }

        #endregion 属性
    }
}